/**
 * 描述:
 *
 * 1.kafka架构设计
 *      1.group消费者组：一个组内的消费者分别消费不同分区的数据
 *      2.topic：队列，topic将消息分类，生产者和消费者面向的是同一个topic
 *      3.partition：一个topic消息可以存储到多个partition中，partition分布在多个broker中，一个topic的每个partition可以有多个副本，
 *        一个Leader和若干个flower，他们是集群关系，可以高可用
 *      4.offset：消费者消费的位置信息，监控数据消费到什么位置，当消费者挂掉重连时，还能从位置开始消费
 *      5.zookeeper：注册中心，管理集群
 *  3.kafka是pull还是push？优劣势分析
 *      1.采用pull
 *          根据consumer的消费能力进行拉取，控制速率
 *          可以批量拉取，或者单挑拉取
 *          可以设置不同的提交方式
 *          问题：consumer会空循环，消耗资源
 *          解决：通过参数设置，可以设置拉取没有数据进行阻塞
 *  4.kafka高性能的原因
 *      1.顺序写
 *          1.kafka不是内存，是基于硬盘存储，消息堆积能力强
 *          2.利用磁盘的顺序写，消息都是append操作，可以接近内存，节省了磁盘的寻道时间，可以通过批量操作，节省写入次数
 *      2.压缩传输
 *          1.减少网络压力，producer进行压缩整合发送
 *      3.基于netty的零拷贝
 *          1.传统：磁盘文件数据->内核缓冲区->用户缓冲区->到socket缓冲区->网卡
 *          2.零拷贝：内核缓冲区->网卡
 *      4.pull方式
 *      5.partition,group
 *      6.批量发送
 *          1.producer发送消息时，可以将消息缓存在本地，等到了固定条件发送到broker中
 *  5.什么场景使用了mq
 *      1.异步，解耦，削峰
 *      2.发送日志，如果是将日志存入数据库
 *      3.请求需要快速响应的时候
 *      4.多个业务需要处理相同的消息，比如订单消息，异步同时处理消息，类似多线程处理，提高效率
 *      5.减少高峰时器服务器的压力，一些业务可以存到消息队列中慢慢处理
 *  6.mq缺点：
 *      1.系统的复杂性变高了，引入了新的中间件，就得考虑它的高可用，消息丢失，重复消费，消息持久化等等问题
 *      2.产生一致性问题，有点像分布式事务，一条消息两个业务系统处理成功了，另外一个失败了怎么办
 *  7.四大消息中间件对比
 *      1.吞吐量优先：选择kafka和rocketmq，activemq和rabbitmq低一个数量级
 *      2.社区活跃度：activemq已经不维护了，快被淘汰了，其它三个社区都很活跃
 *      3.时效性：rabbitmq是最好的，微妙级别
 *      4.可用性：activemq和rabbitmq主从架构，kafak基于zookeeper的分布式架构，多副本，保证数据不丢失，rocketmq分布式架构，可用性非常高，
 *      5.消息可靠性：activemq可能会导致消息丢失，kafka和rocketmq配置好可以保证0丢失
 *      6.语言上的选型：rabbitmq是erlang语言写的，不好看源码，不好修改，kafka是java写的
 *      7.技术上选型：要保证低延迟，选rabbitmq，保证高吞吐量，选rocektmq或者kafka，但是kafka的吞吐量会随着topic的增加而变少
 *  8.kafka如何保证消息高可用
 *      1.架构
 *          1.broker:集群节点，三个节点就是三个Broker，broker存储topic的消息
 *          2.topic:一个类别，是kafka发送消息选择的一个标识吧
 *          3.partition:分区，消息会被存储到partition中，一个broker可能可以有多个partition，一个消息可能有多个副本，分布存到不通的partition中，保证消息的均匀分布
 *              如果一台服务器挂了，其它partition可能还存储这个topic的副本，还可以继续保证可用
 *          4.group:组，一个组可以消费一个Topic的消息，多个组会消费多次一个topic的消息，一个concumer只能是一个组
 *          5.producer:生产者
 *          6:consumer:消费者
 *          7.leader:集群的leader节点
 *          8.flower:集群的flower节点
 *      2.如何保证高可用：
 *          1.数据副本：kafak写入数据的时候，会先写入leader节点，然后将数据同步到flower节点。取决于创建topic的时候会建立几个数据副本。
 *              如果一台kafka挂了，则可以从其它的副本flower服务器读取分区数据，保证可用
 *          2.ISR机制：leader会跟踪与其保持同步的一个replice列表，叫做ISR，如果一个flower宕机太久，就会被ISR剔除，ISR是存储在zookeeper的，相当于一个集群列表。如果leader
 *              宕机了，ISR就会选举一个新的Leader
 *          3.ACK机制：kafka可以设置ack，一种是数据一旦发出去就当作服务器已经收到，一种是数据在leader节点落盘后，返回收到的ack，一种是数据同步到flower，
 *              半数以上flower成功同步的时候，返回ack，一种是全部同步后返回ack
 *              第四种是可以最好的保证消息被Broker接收到，但是吞吐量必定是会下载的，而且受副本数量的影响
 *  9.kafka如何保证消息不被重复消费（幂等）：
 *      产生问题的原因：kafka消费消息会定期commit，如果消费了消息还没commit，突然宕机了，则offset还在上次的位置，就会重复消费一些消息
 *      1.在业务端进行保证，可以引入redis，存储唯一的值，然后业务上用redis进行去重判断和消费判断
 *      2.用CAS，修改的时候，先去判断数据库中的数据状态跟现在的数据状态是否一致，一致则修改，比如update set a = a + 1 where status = 0
 *      3.乐观锁：update aa set a = a + 1 , version = version + 1 where version = x
 *
 *  10.kafka如何保证消息的顺序消费
 *      1.一个topic只有一个partition，然后一个消费者，吞吐量太低
 *      2.一个topic多个partition，多个消费者，内存队列排序消费，业务上做控制
 *      3.消息间的顺序保证，比如业务上先处理A，再处理B，那就把A和B的消息放到同一条消息中去处理
 *      4.kafka为了保证统一类型消息的顺序性，要求一个partition只能被同一组的一个consumer消费
 *  11.如何解决消息队列的延时以及过期失效问题，消息队列满了以后该怎么处理，有几百万消息持续积压几小时，说说怎么解决
 *      1.临时紧急扩容
 *          1.修复consumer问题，确保其恢复消费速度，然后停掉现有consumer；
 *          2.新建topic并设置原来10倍或者20倍的partition，不管是改原来的消费者将消息写入新partition，还是直接处理积压的消息进partition，新建10倍或20倍的consumer，来处理消息并写库；
 *          3.等快速消费完积压数据后，恢复原先的部署架构，重新用原来的consumer机器来消费数据
 *      2.过期问题
 *          1.kafka可以设置消息的过期时间，一般七天失效
 *      3.队列满了
 *          1.临时写一个消费者消费消息，消费一个丢一个，然后存消息到一个地方，下次扩容后再写入
 *  12.kafka消息消费失败了怎么办
 *      1.kafka没有自动的重试机制，消息消费失败需要做额外处理
 *      2.将消费失败的数据存入数据库中，定义一张消息id，消息内容，消息重试次数的表，然后发送到topic中继续尝试，达到重试次数失败就人工干预
 *  13.kafka如何保证消息不丢失
 *      1.消息丢失的情况：
 *          1.producer 端 发送消息给kafka server 端，中间网络出现问题，消息无法送达
 *          2.kafka server端 在收到消息以后，保存消息时发生异常,异常分为三种
 *              1.可重试错误，通过重试来解决
 *              2.no leader错误，
 *              3.网络连接错误
 *          3.consumer在消费时发生异常
 *              1.consumer 端启用了 enable.auto.commit= true,在消费消息时发生了异常
 *              2.consumer 端 enable.auto.commit= false，但是在消息消费之前，提交了offset
 *      2.解决方式：
 *          1.producer端优化：
 *              1.producer发送，代码中有异步发送，同步发送，简单发送
 *                  1.简单发送：消息无感知，不知道是成功还是失败
 *                  2.同步发送：可以得到发送的ack返回结果，但是同步的效率太低
 *                  3.异步发送：可以定义发送消息失败的处理
 *              2.producer端配置优化：
 *                  1.acks参数
 *                      1.=0表示producer将消息写入broker不会返回任何响应
 *                      2.=1表示leader节点接受到消息并且落入磁盘返回响应
 *                      3.=ALL表示所有节点收到消息落入磁盘返回响应
 *                  2.retries参数
 *                      1.消息发送时，产生临时性错误的重试次数，如果重试超过该次数，则异常
 *              3.可以通过配置acks和retries来保证消息不丢失，设置ack=ALL和retries的重试次数多一点
 *              4.可以将发送失败的消息存入本地消息表中，然后定时再去发送
 *          2.server端优化：
 *              1.kafka的server端同一个topic下有多个分区，单个分区会有不同的副本。如果producer 发送消息么kafka server端，leader收到了消息以后，告诉producer
 *                发送成功，此时再同步消息到多个副本，但由于某一个副本同步较慢，此时leader挂了，需要选主，选主的过程中，一旦那个较慢的副本成为新的leader，
 *                那么新的leader中就不包含了原leader收到的那条最新数据，导致消息丢失
 *              2.配置选项：unclean.leader.election.enable = false，表示不允许非ISR中的副本被选举为领导
 *                  1.ISR：是指与leader保持一定程度（这种范围是可通过参数进行配置的）同步的副本和 leader 共同被称为ISR
 *                  2.OSR：与leader同步时，滞后很多的副本（不包括leader）被称为OSR
 *          3.consumer端优化：
 *              1.设置 enable.auto.commit = false
 *              2.在consumer端消费消息操作完成以后 再同步或者异步手动提交 offset
 *  14.kafka重平衡rebalance
 *      1.分区的所有劝从一个消费者转移到了另一个消费者，重平衡实现了消费者的高可用和伸缩性，主要是消费者通过群组协调器的Broker发送心跳来维护群组的从属关系以及分区的所有权
 *      2.比如：有100个分区，有5个消费者，那平均每个消费者20个分区。这时候，突然一个消费者挂了，心跳没了，那就会发生重平衡，让剩下的4个消费者每个拥有25个分区
 *      3.触发时机：
 *          1.组成员数发生变更（可能由于网络断开，服务挂了等等，没有心跳了）
 *          2.订阅的主题数变更了，比如用正则表达式订阅topic，这时候有一个topic删除了
 *          3.订阅主题数分区发生变更，kafka允许增加分区
 *      4.问题：导致消费者无法消费，等待重平衡完成，而且重平衡太慢了，几百个consumer要几个小时，对TPS影响很大
 *      5.如何避免：
 *          1.针对未及时发送心跳的情况：设置 session.timeout.ms = 6s  设置 heartbeat.interval.ms = 2s ，保证至少发送三轮心跳才会提出群组
 *          2.避免消费者消费的时间过长，或者把max.poll.interval.ms设置的大一点
 * @author
 * @created 2022/2/8 10:51
 */
public class MQ {
}
